﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WenCong.WorkShop.FrameWork.Orm;

namespace WenCong.WorkShop.Framework.Orm
{
    public class BaseDao<T> where T : new()
    {
        private const string WriteConnectionNameEx = "_Write";

        private readonly bool _enableRw = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["EnableRW"]) &&
                                          Convert.ToBoolean(ConfigurationManager.AppSettings["EnableRW"]);

        public BaseDao()
        {
            ConnectionStringName = DbFactoryAttribute.GetKeyFrom(this);
        }

        public string ConnectionStringName { get; set; }

        private Database ReadDatabase
        {
            get { return new Database(ConnectionStringName); }
        }

        public Database WriteDatabase
        {
            get
            {
                return _enableRw
                    ? new Database(ConnectionStringName + WriteConnectionNameEx)
                    : new Database(ConnectionStringName);
            }
        }

        public void Save(T info)
        {
             WriteDatabase.Save(info);
        }

        public object Add(T info)
        {
            return WriteDatabase.Insert(info);
        }

        public object Insert(T info)
        {
            return WriteDatabase.Insert(info);
        }

        public int Update(T info)
        {
            return WriteDatabase.Update(info);
        }

        public int Update(Sql sql)
        {
            return WriteDatabase.Update(sql);
        }

        public int Delete(T info)
        {
            return WriteDatabase.Delete(info);
        }

        public int Delete(Sql sql)
        {
            return WriteDatabase.Delete<T>(sql);
        }

        public int DeleteById(object primaryKey)
        {
            return WriteDatabase.Delete<T>(primaryKey);
        }

        public T GetById(object primaryKey)
        {
            return ReadDatabase.SingleOrDefault<T>(primaryKey);
        }

        public T FirstOrDefault(Sql sql)
        {
            return Query(sql).FirstOrDefault();
        }

        public TDto FirstOrDefault<TDto>(Sql sql)
        {
            return Query<TDto>(sql).FirstOrDefault();
        }

        public List<T> Query(Sql sql)
        {
            return ReadDatabase.Query<T>(sql).ToList();
        }

        public List<TDto> Query<TDto>(Sql sql)
        {
            return ReadDatabase.Query<TDto>(sql).ToList();
        }

        public Page<T> Page(int pageIndex, int pageSize, Sql sql)
        {
            return ReadDatabase.Page<T>(pageIndex, pageSize, sql);
        }

        public Page<TDto> Page<TDto>(int pageIndex, int pageSize, Sql sql)
        {
            return ReadDatabase.Page<TDto>(pageIndex, pageSize, sql);
        }

        public int Execute(Sql sql)
        {
            return WriteDatabase.Execute(sql);
        }

        public void BatchInsert(List<T> list)
        {
            int pageIndex = 1;
            const int pageSize = 50;
            while (true)
            {
                int itemCount = (pageIndex - 1) * pageSize;
                //if (list.Count <= itemCount) break;

                IEnumerable<object> tempList = (IEnumerable<object>) list.Skip(itemCount).Take(pageSize);
                if (!tempList.Any() ) break;

                WriteDatabase.BulkInsert(tempList);
                pageIndex += 1;
            }
        }

        ///// <summary>
        ///// 执行SQL返回DataTable
        ///// </summary>
        ///// <param name="strSql">SQL语句，也可以是存储过程</param>
        ///// <param name="args"></param>
        ///// <returns></returns>
        //public DataTable Execute(string strSql, params object[] args)
        //{
        //    DataTable dt = new DataTable();
        //    WriteDatabase.Fill(dt, strSql, args);
        //    return dt;
        //}
    }
}
